home *** CD-ROM | disk | FTP | other *** search
- /* The way of garbage collecting which allows use of the cstack is due to
- * SIOD by George Carrette.
- */
-
- #include <stdio.h>
- #include "_scm.h"
-
-
-
-
- #ifdef __STDC__
- SCM
- scm_gc_for_newcell (void)
- #else
- SCM
- scm_gc_for_newcell ()
- #endif
- {
- SCM fl;
- scm_gc_for_alloc (1, &scm_freelist);
- fl = scm_freelist;
- scm_freelist = CDR (fl);
- return fl;
- }
-
- static char s_bad_type[] = "unknown type in ";
- jmp_buf scm_save_regs_gc_mark;
-
-
- #define HUGE_LENGTH(x) (LENGTH_MAX==LENGTH(x) ? *((long *)VELTS(x)) : LENGTH(x))
-
- #ifdef __STDC__
- void
- scm_gc_sweep (void)
- #else
- void
- scm_gc_sweep ()
- #endif
- {
- register CELLPTR ptr;
- #ifdef POINTERS_MUNGED
- register SCM scmptr;
- #else
- #define scmptr (SCM)ptr
- #endif
- register SCM nfreelist;
- register SCM *hp_freelist;
- register long n;
- register long m;
- register sizet j;
- register int span;
- sizet i;
- sizet seg_size;
-
- n = 0;
- m = 0;
- i = 0;
-
- while (i < scm_n_heap_segs)
- {
- hp_freelist = scm_heap_table[i].freelistp;
- nfreelist = EOL;
- span = scm_heap_table[i].ncells;
- ptr = CELL_UP (scm_heap_table[i].bounds[0]);
- seg_size = CELL_DN (scm_heap_table[i].bounds[1]) - ptr;
- ++i;
- for (j = seg_size + span; j -= span; ptr += span)
- {
- #ifdef POINTERS_MUNGED
- scmptr = PTR2SCM (ptr);
- #endif
- switch TYP7 (scmptr)
- {
- case tcs_cons_gloc:
- if (GCMARKP (scmptr))
- {
- if (CDR (CAR (scmptr) - 1) == (SCM)1)
- CDR (CAR (scmptr) - 1) = (SCM)0;
- goto cmrkcontinue;
- }
- {
- SCM vcell;
- vcell = CAR (scmptr) - 1L;
- if ((CDR (vcell) == 0) || (CDR (vcell) == 1))
- {
- free ((char *)CDR (scmptr));
- m += sizeof (SCM) * (LENGTH (((SCM *)vcell)[struct_i_format]));
- CDR (scmptr) = BOOL_F;
- --((SCM *)vcell)[struct_i_refcnt];
- }
- }
- break;
- case tcs_cons_imcar:
- case tcs_cons_nimcar:
- case tcs_closures:
- if (GCMARKP (scmptr))
- goto cmrkcontinue;
- break;
- case tc7_vector:
- case tc7_lvector:
- #ifdef CCLO
- case tc7_cclo:
- #endif
- if (GC8MARKP (scmptr))
- goto c8mrkcontinue;
- m += (LENGTH (scmptr) * sizeof (SCM));
- freechars:
- scm_must_free (CHARS (scmptr));
- /* SETCHARS(scmptr, 0);*/
- break;
- case tc7_bvect:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += sizeof (long) * ((HUGE_LENGTH (scmptr) + LONG_BIT - 1) / LONG_BIT);
- goto freechars;
- case tc7_ivect:
- case tc7_uvect:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += HUGE_LENGTH (scmptr) * sizeof (long);
- goto freechars;
- case tc7_fvect:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += HUGE_LENGTH (scmptr) * sizeof (float);
- goto freechars;
- case tc7_dvect:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += HUGE_LENGTH (scmptr) * sizeof (double);
- goto freechars;
- case tc7_cvect:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += HUGE_LENGTH (scmptr) * 2 * sizeof (double);
- goto freechars;
- case tc7_string:
- if (GC8MARKP (scmptr))
- goto c8mrkcontinue;
- m += HUGE_LENGTH (scmptr) + 1;
- goto freechars;
- case tc7_msymbol:
- if (GC8MARKP (scmptr))
- goto c8mrkcontinue;
- m += LENGTH (scmptr) + 1;
- scm_must_free ((char *)SLOTS (scmptr));
- break;
- case tc7_contin:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += LENGTH (scmptr) * sizeof (STACKITEM) + sizeof (regs);
- goto freechars;
- case tc7_ssymbol:
- if GC8MARKP(scmptr)
- goto c8mrkcontinue;
- break;
- case tcs_subrs:
- continue;
- case tc7_port:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- if OPENP (scmptr)
- {
- int k = PTOBNUM (scmptr);
- if (!(k < scm_numptob))
- goto sweeperr;
- /* Keep "revealed" ports alive. */
- if (scm_revealed_count(scmptr) > 0)
- continue;
- /* Yes, I really do mean scm_ptobs[k].free */
- /* rather than ftobs[k].close. .close */
- /* is for explicit CLOSE-PORT by user */
- (scm_ptobs[k].free) (STREAM (scmptr));
- scm_remove_from_port_table (scmptr);
- scm_gc_ports_collected++;
- SETSTREAM (scmptr, 0);
- CAR (scmptr) &= ~OPN;
- }
- break;
- case tc7_smob:
- switch GCTYP16 (scmptr)
- {
- case tc_free_cell:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- break;
- #ifdef BIGDIG
- case tcs_bignums:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- m += (NUMDIGS (scmptr) * BITSPERDIG / CHAR_BIT);
- goto freechars;
- #endif /* def BIGDIG */
- case tc16_flo:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
- switch ((int) (CAR (scmptr) >> 16))
- {
- case (IMAG_PART | REAL_PART) >> 16:
- m += sizeof (double);
- case REAL_PART >> 16:
- case IMAG_PART >> 16:
- m += sizeof (double);
- goto freechars;
- case 0:
- break;
- default:
- goto sweeperr;
- }
- break;
- default:
- if GC8MARKP (scmptr)
- goto c8mrkcontinue;
-
- {
- int k;
- k = SMOBNUM (scmptr);
- if (!(k < scm_numsmob))
- goto sweeperr;
- m += (scm_smobs[k].free) ((SCM) scmptr);
- break;
- }
- }
- break;
- default:
- sweeperr:scm_wta (scmptr, s_bad_type, "gc_sweep");
- }
- n += span;
- #if 0
- if (CAR (scmptr) == (SCM) tc_free_cell)
- exit (2);
- #endif
- CAR (scmptr) = (SCM) tc_free_cell;
- CDR (scmptr) = nfreelist;
- nfreelist = scmptr;
- #if 0
- if ((nfreelist < scm_heap_table[0].bounds[0]) ||
- (nfreelist >= scm_heap_table[0].bounds[1]))
- exit (1);
- #endif
- continue;
- c8mrkcontinue:
- CLRGC8MARK (scmptr);
- continue;
- cmrkcontinue:
- CLRGCMARK (scmptr);
- }
- #ifdef GC_FREE_SEGMENTS
- if (n == seg_size)
- {
- scm_heap_size -= seg_size;
- scm_must_free ((char *) scm_heap_table[i - 1].bounds[0]);
- scm_heap_table[i - 1].bounds[0] = 0;
- for (j = i; j < scm_n_heap_segs; j++)
- scm_heap_table[j - 1] = scm_heap_table[j];
- scm_n_heap_segs -= 1;
- i -= 1; /* need to scan segment just moved. */
- }
- else
- #endif /* ifdef GC_FREE_SEGMENTS */
- *hp_freelist = nfreelist;
-
- scm_gc_cells_collected += n;
- n = 0;
- }
- scm_lcells_allocated += ( scm_heap_size
- - scm_gc_cells_collected
- - scm_cells_allocated);
- scm_cells_allocated = (scm_heap_size - scm_gc_cells_collected);
- scm_lmallocated -= m;
- scm_mallocated -= m;
- scm_gc_malloc_collected = m;
- }
-
- STACKITEM * scm_stack_base = 0;
-
- #ifdef __STDC__
- void
- scm_igc (char *what)
- #else
- void
- scm_igc (what)
- char *what;
- #endif
- {
- int j;
- long oheap_size;
-
- j = scm_num_protects;
- oheap_size = scm_heap_size;
-
- scm_gc_start (what);
- ++scm_errjmp_bad;
-
- {
- SCM type_list;
- SCM * pos;
-
- pos = &type_obj_list;
- type_list = type_obj_list;
- while (type_list != EOL)
- if (VELTS (CAR (type_list))[struct_i_refcnt])
- {
- pos = &CDR (type_list);
- type_list = CDR (type_list);
- }
- else
- {
- *pos = CDR (type_list);
- type_list = CDR (type_list);
- }
- }
-
- while (j--)
- scm_gc_mark (scm_sys_protects[j]);
-
- scm_mark_arrays ();
-
- FLUSH_REGISTER_WINDOWS;
- /* This assumes that all registers are saved into the jmp_buf */
- setjmp (scm_save_regs_gc_mark);
- scm_mark_locations ((STACKITEM *) scm_save_regs_gc_mark,
- ( (sizet) sizeof scm_save_regs_gc_mark
- / sizeof (STACKITEM)));
-
- {
- /* stack_len is long rather than sizet in order to guarantee that
- &stack_len is long aligned */
- #ifdef STACK_GROWS_UP
- #ifdef nosve
- long stack_len = (STACKITEM *) (&stack_len) - scm_stack_base;
- #else
- long stack_len = stack_size (scm_stack_base);
- #endif
- scm_mark_locations (scm_stack_base, (sizet) stack_len);
- #else
- #ifdef nosve
- long stack_len = scm_stack_base - (STACKITEM *) (&stack_len);
- #else
- long stack_len = scm_stack_size (scm_stack_base);
- #endif
- scm_mark_locations ((scm_stack_base - stack_len), (sizet) stack_len);
- #endif
- }
- scm_gc_sweep ();
-
- --scm_errjmp_bad;
- scm_gc_end ();
-
-
- if (oheap_size != scm_heap_size)
- {
- ALLOW_INTS;
- scm_growth_mon ("heap", scm_heap_size, "cells");
- DEFER_INTS;
- }
- }
-
- extern scm_cell scm_tmp_errp;
-
- static char s_not_free[] = "not freed";
- #ifdef __STDC__
- void
- scm_free_storage (void)
- #else
- void
- scm_free_storage ()
- #endif
- {
- sizet i = 0;
-
- DEFER_INTS;
- scm_gc_start ("free");
- ++scm_errjmp_bad;
- cur_inp = BOOL_F;
- cur_outp = BOOL_F;
- cur_errp = PTR2SCM (&scm_tmp_errp);
- scm_gc_mark (def_inp); /* don't want to close stdin */
- scm_gc_mark (def_outp); /* don't want to close stdout */
- scm_gc_mark (def_errp); /* don't want to close stderr */
- scm_gc_sweep ();
- rootcont = BOOL_F;
- while (i < scm_n_heap_segs)
- { /* free heap segments */
- CELLPTR ptr;
- sizet seg_size;
-
- ptr = CELL_UP (scm_heap_table[i].bounds[0]);
- seg_size = CELL_DN (scm_heap_table[i].bounds[1]) - ptr;
- scm_heap_size -= seg_size;
- scm_must_free ((char *) scm_heap_table[i].bounds[0]);
- scm_heap_table[i].bounds[0] = 0;
- scm_growth_mon ("heap", scm_heap_size, "cells");
- ++i;
- }
- if (scm_heap_size)
- scm_wta (MAKINUM (scm_heap_size), s_not_free, "heap");
-
- /* Not all cells get freed (see scm_gc_mark() calls above). */
- /* if (scm_cells_allocated) scm_wta(MAKINUM(scm_cells_allocated), s_not_free, "cells"); */
- /* either there is a small memory leak or I am counting wrong. */
- /* if (scm_mallocated) scm_wta(MAKINUM(scm_mallocated), s_not_free, "malloc"); */
-
- scm_must_free ((char *) scm_heap_table);
- scm_heap_table = 0;
- scm_must_free ((char *) scm_smobs);
- scm_smobs = 0;
- scm_gc_end ();
- ALLOW_INTS; /* A really bad idea, but printing does it anyway. */
- scm_exit_report ();
- scm_must_free ((char *) scm_ptobs);
- scm_ptobs = 0;
- scm_lmallocated = scm_mallocated = 0;
- /* Can't do scm_gc_end() here because it uses scm_ptobs which have been freed */
- }
-
- #ifdef __STDC__
- void
- scm_gc_mark (SCM p)
- #else
- void
- scm_gc_mark (p)
- SCM p;
- #endif
- {
- register long i;
- register SCM ptr;
-
- ptr = p;
-
- gc_mark_loop:
- if (IMP (ptr))
- return;
-
- gc_mark_nimp:
- if (NCELLP (ptr))
- scm_wta (ptr, "rogue pointer in ", "heap");
-
- switch (TYP7 (ptr))
- {
- case tcs_cons_nimcar:
- if (GCMARKP (ptr))
- break;
- SETGCMARK (ptr);
- if (IMP (CDR (ptr))) /* IMP works even with a GC mark */
- {
- ptr = CAR (ptr);
- goto gc_mark_nimp;
- }
- scm_gc_mark (CAR (ptr));
- ptr = GCCDR (ptr);
- goto gc_mark_nimp;
- case tcs_cons_imcar:
- if (GCMARKP (ptr))
- break;
- SETGCMARK (ptr);
- ptr = GCCDR (ptr);
- goto gc_mark_loop;
- case tcs_cons_gloc:
- if (GCMARKP (ptr))
- break;
- SETGCMARK (ptr);
- {
- SCM vcell;
- vcell = CAR (ptr) - 1L;
- switch (CDR (vcell))
- {
- default:
- scm_gc_mark (vcell);
- ptr = GCCDR (ptr);
- goto gc_mark_loop;
- case 1: /* ! */
- case 0: /* ! */
- {
- char * format;
- int len;
- int i;
- SCM * mem;
- format = CHARS ( ((SCM *)vcell)[struct_i_format] );
- len = LENGTH ( ((SCM *)vcell)[struct_i_format] );
- mem = (SCM *)GCCDR (ptr);
- for (i = 0; i < len; ++i, ++format)
- if ((*format == 's') || (*format == 'S'))
- scm_gc_mark (mem[i]);
- else if (*format == '*')
- {
- int vlen;
- vlen = mem[i];
- ++format;
- ++i;
- if ((*format == 's') || (*format == 'S'))
- {
- int j;
- for (j = 0; j < vlen; ++j)
- scm_gc_mark (mem[i + j]);
- }
- }
- }
- if (!CDR (vcell))
- {
- SETGCMARK (vcell);
- ptr = ((SCM *)vcell)[struct_i_self];
- goto gc_mark_loop;
- }
- }
- }
- break;
- case tcs_closures:
- if (GCMARKP (ptr))
- break;
- SETGCMARK (ptr);
- if (IMP (CDR (ptr)))
- {
- ptr = CLOSCAR (ptr);
- goto gc_mark_nimp;
- }
- scm_gc_mark (CLOSCAR (ptr));
- ptr = GCCDR (ptr);
- goto gc_mark_nimp;
- case tc7_vector:
- case tc7_lvector:
- #ifdef CCLO
- case tc7_cclo:
- #endif
- if (GC8MARKP (ptr))
- break;
- SETGC8MARK (ptr);
- i = LENGTH (ptr);
- if (i == 0)
- break;
- while (--i > 0)
- if (NIMP (VELTS (ptr)[i]))
- scm_gc_mark (VELTS (ptr)[i]);
- ptr = VELTS (ptr)[0];
- goto gc_mark_loop;
- case tc7_contin:
- if GC8MARKP
- (ptr) break;
- SETGC8MARK (ptr);
- scm_mark_locations (VELTS (ptr),
- (sizet) (LENGTH (ptr) + sizeof (regs) / sizeof (STACKITEM)));
- break;
- case tc7_bvect:
- case tc7_ivect:
- case tc7_uvect:
- case tc7_fvect:
- case tc7_dvect:
- case tc7_cvect:
- case tc7_string:
- SETGC8MARK (ptr);
- break;
- case tc7_msymbol:
- if (GC8MARKP(ptr))
- break;
- SETGC8MARK (ptr);
- scm_gc_mark (SYMBOL_FUNC (ptr));
- ptr = SYMBOL_PROPS (ptr);
- goto gc_mark_loop;
- case tc7_ssymbol:
- if (GC8MARKP(ptr))
- break;
- SETGC8MARK (ptr);
- break;
- case tcs_subrs:
- break;
- case tc7_port:
- i = PTOBNUM (ptr);
- if (!(i < scm_numptob))
- goto def;
- ptr = (scm_ptobs[i].mark) (ptr);
- goto gc_mark_loop;
- break;
- case tc7_smob:
- if (GC8MARKP (ptr))
- break;
- switch TYP16 (ptr)
- { /* should be faster than going through scm_smobs */
- case tc_free_cell:
- /* printf("found free_cell %X ", ptr); fflush(stdout); */
- SETGC8MARK (ptr);
- CDR (ptr) = EOL;
- break;
- case tcs_bignums:
- case tc16_flo:
- SETGC8MARK (ptr);
- break;
- default:
- i = SMOBNUM (ptr);
- if (!(i < scm_numsmob))
- goto def;
- ptr = (scm_smobs[i].mark) (ptr);
- goto gc_mark_loop;
- }
- break;
- default:
- def:scm_wta (ptr, s_bad_type, "gc_mark");
- }
- }
-
- #ifdef __STDC__
- void
- scm_mark_locations (SCM_STACKITEM x[], sizet n)
- #else
- void
- scm_mark_locations (x, n)
- SCM_STACKITEM x[];
- sizet n;
- #endif
- {
- register long m = n;
- register int i, j;
- register CELLPTR ptr;
-
- while (0 <= --m)
- if CELLP (*(SCM **) & x[m])
- {
- ptr = (CELLPTR) SCM2PTR ((*(SCM **) & x[m]));
- i = 0;
- j = scm_n_heap_segs - 1;
- if ( PTR_LE (scm_heap_table[i].bounds[0], ptr)
- && PTR_GT (scm_heap_table[j].bounds[1], ptr))
- {
- while (i <= j)
- {
- int seg_id;
- seg_id = -1;
- if ( (i == j)
- || PTR_GT (scm_heap_table[i].bounds[1], ptr))
- seg_id = i;
- else if (PTR_LE (scm_heap_table[j].bounds[0], ptr))
- seg_id = j;
- else
- {
- int k;
- k = (i + j) / 2;
- if (k == i)
- break;
- if (PTR_GT (scm_heap_table[k].bounds[1], ptr))
- {
- j = k;
- ++i;
- if (PTR_LE (scm_heap_table[i].bounds[0], ptr))
- continue;
- else
- break;
- }
- else if (PTR_LE (scm_heap_table[k].bounds[0], ptr))
- {
- i = k;
- --j;
- if (PTR_GT (scm_heap_table[j].bounds[1], ptr))
- continue;
- else
- break;
- }
- }
- if ( !scm_heap_table[seg_id].valid
- || scm_heap_table[seg_id].valid (ptr,
- &scm_heap_table[seg_id]))
- scm_gc_mark (*(SCM *) & x[m]);
- break;
- }
-
- }
- }
- }
-
-
-